namespace CookieTerm.MdiTabStrip
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    using System.ComponentModel;
    using System.Drawing.Drawing2D;
    using System.Runtime.InteropServices;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Drawing.Imaging;

    /// <summary>
    /// Represents a selectable tab that corresponds to exactly one open <see cref="Form"/> 
    /// whose <see cref="Form.MdiParent"/> property has been 
    /// set to an instance of another form in an MDI application.
    /// </summary>
    [ToolboxItem(false)]
    public class MdiTab : MdiTabStripItemBase
    {

        #region "Fields"
        private MdiTabStrip m_owner;
        private Form m_form;
        private bool m_isMouseOver = false;
        private bool m_isMouseOverCloseButton = false;
        private bool m_isSwitching = false;
        private Rectangle m_dragBox = Rectangle.Empty;
        private Point[] m_activeBounds;
        private Point[] m_activeInnerBounds;
        private Point[] m_inactiveBounds;
        private Point[] m_inactiveInnerBounds;
        private Point[] m_closeButtonBounds;
        private Point[] m_closeButtonGlyphBounds;
        private Cursor m_dragCursor = null;
        private bool m_isAnimating = false;
        private AnimationType m_animationType;
        #endregion
        private int m_currentFrame = 0;

        #region "Constructor/Destructor"
        /// <summary>
        /// Initializes a new instance of the <see cref="MdiTab"/> class.
        /// </summary>
        public MdiTab(MdiTabStrip owner)
        {
            this.ParentInternal = owner;
        }

        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="MdiTab"/> and optionally releases the managed resources. 
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.m_dragCursor != null)
                {
                    this.m_dragCursor.Dispose();
                }
            }

            base.Dispose(disposing);
        }
        #endregion

        #region "Properties"
        /// <summary>
        /// Gets or sets the instance of a <see cref="Form"/> the <see cref="MdiTab"/> represents.
        /// </summary>
        /// <returns>The <see cref="Form"/> object the tab represents.</returns>
        public Form Form
        {
            get { return this.m_form; }
            set { this.m_form = value; }
        }

        internal MdiTabStrip ParentInternal
        {
            get { return this.m_owner; }
            set { this.m_owner = value; }
        }

        internal bool IsMouseOver
        {
            get { return this.m_isMouseOver; }
            set { this.m_isMouseOver = value; }
        }

        internal bool IsActive
        {
            get { return object.ReferenceEquals(this.ParentInternal.ActiveTab, this); }
        }

        private bool IsAnimating
        {
            get { return this.m_isAnimating; }
            set
            {
                this.m_isAnimating = value;

                if (value)
                {
                    this.ParentInternal.AddAnimatingTab(this);
                }
                else
                {
                    this.ParentInternal.RemoveAnimatingTab(this);
                    this.m_animationType = AnimationType.None;
                }
            }
        }

        internal int CurrentFrame
        {
            get { return this.m_currentFrame; }
            set { this.m_currentFrame = value; }
        }

        internal AnimationType AnimationType
        {
            get { return this.m_animationType; }
        }

        /// <summary>
        /// Gets the rectangle that represents the display area of the control.
        /// </summary>
        /// <returns>A <see cref="Rectangle"/> that represents the display area of the control.</returns>
        public override System.Drawing.Rectangle DisplayRectangle
        {
            get
            {
                Rectangle rect = base.DisplayRectangle;
                rect.Offset(this.Location.X, this.Location.Y);
                return rect;
            }
        }

        internal bool IsMouseOverCloseButton
        {
            get { return this.m_isMouseOverCloseButton; }
            set
            {
                if (this.m_isMouseOverCloseButton != value)
                {
                    string txt = this.Form.Text;

                    this.m_isMouseOverCloseButton = value;

                    if (value)
                    {
                        txt = "Close Tab";
                    }

                    if (this.ParentInternal.ShowTabToolTip)
                    {
                        this.ParentInternal.UpdateToolTip(txt);
                    }

                    this.ParentInternal.Invalidate();
                }
            }
        }

        internal bool CanDrag
        {
            get
            {
                if (this.ParentInternal.Tabs.Count == 1)
                {
                    return false;
                }

                return !(this.ParentInternal.TabPermanence == MdiTabPermanence.First & (this.ParentInternal.Tabs.IndexOf(this) == 0));
            }
        }

        internal bool CanClose
        {
            get
            {
                if (this.ParentInternal.TabPermanence == MdiTabPermanence.First && (this.ParentInternal.Tabs.IndexOf(this) == 0))
                {
                    return false;
                }
                else if (this.ParentInternal.TabPermanence == MdiTabPermanence.LastOpen && this.ParentInternal.Tabs.Count == 1)
                {
                    return false;
                }

                return true;
            }
        }

        private bool CanAnimate
        {
            get { return this.ParentInternal.Animate; }
        }

        private Color TabBackColor
        {
            get
            {
                Color tabcolor = this.ParentInternal.InactiveTabColor;

                if (this.IsActive)
                {
                    tabcolor = this.ParentInternal.ActiveTabColor;
                }
                else if (!this.Enabled)
                {
                    tabcolor = this.ParentInternal.InactiveTabColor;
                }
                else if (this.IsAnimating)
                {
                    tabcolor = this.ParentInternal.BackColorFadeSteps[this.m_currentFrame];
                }
                else if (this.IsMouseOver)
                {
                    tabcolor = this.ParentInternal.MouseOverTabColor;
                }

                return tabcolor;
            }
        }

        protected Color TabForeColor
        {
            get
            {
                Color foreColor = this.ParentInternal.InactiveTabForeColor;

                if (this.IsActive)
                {
                    foreColor = this.ParentInternal.ActiveTabForeColor;
                }
                else if (this.IsAnimating)
                {
                    foreColor = this.ParentInternal.ForeColorFadeSteps[this.m_currentFrame];
                }
                else if (this.IsMouseOver)
                {
                    foreColor = this.ParentInternal.MouseOverTabForeColor;
                }

                return foreColor;
            }
        }

        private Font TabFont
        {
            get
            {
                //We default to the font for the inactive tab because it is more ofter used. If animating we switch
                //to the font for the moused over tab when the current frame is in the latter half of the animation.
                Font font = this.ParentInternal.InactiveTabFont;

                if (this.IsActive)
                {
                    font = this.ParentInternal.ActiveTabFont;
                }
                else if (this.IsAnimating)
                {
                    if (this.CurrentFrame > (this.ParentInternal.Duration / 2))
                    {
                        font = this.ParentInternal.MouseOverTabFont;
                    }
                }
                else if (this.IsMouseOver)
                {
                    font = this.ParentInternal.MouseOverTabFont;
                }

                return font;
            }
        }


        #endregion

        #region "Methods"

        #region "Hit Testing"
        internal bool HitTest(int x, int y)
        {
            bool hit = false;

            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.StartFigure();
                gp.AddLines(m_inactiveBounds);
                gp.CloseFigure();

                using (Pen borderpen = new Pen(Color.Black, 1))
                {
                    if (gp.IsOutlineVisible(x, y, borderpen) || gp.IsVisible(x, y))
                    {
                        hit = true;
                    }
                }
            }

            return hit;
        }

        private bool closeButtonHitTest(int x, int y)
        {
            bool hit = false;

            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.StartFigure();
                gp.AddLines(m_closeButtonBounds);
                gp.CloseFigure();

                using (Pen borderpen = new Pen(Color.Black, 1))
                {
                    if (gp.IsOutlineVisible(x, y, borderpen) || gp.IsVisible(x, y))
                    {
                        hit = true;
                    }
                }
            }

            return hit;
        }
        #endregion

        #region "Paint Background"
        internal void DrawControlBackground(Graphics g)
        {
            if (this.IsActive)
            {
                DrawActiveTabBackground(g);
            }
            else
            {
                DrawInactiveTabBackground(g);
            }
        }

        private void DrawActiveTabBackground(Graphics g)
        {
            //The shadowRectangle fills the divider that is a part of the active tab and spans the width
            //of the parent MdiTabStrip.
            Rectangle shadowRectangle = new Rectangle(this.ParentInternal.ClientRectangle.X, this.DisplayRectangle.Bottom, this.ParentInternal.ClientRectangle.Width, this.ParentInternal.Padding.Bottom);
            Blend shadowBlend = new Blend();

            g.SmoothingMode = SmoothingMode.None;
            shadowBlend.Factors = new float[] {
			0f,
			0.1f,
			0.3f,
			0.4f
		};
            shadowBlend.Positions = new float[] {
			0f,
			0.5f,
			0.8f,
			1f
		};

            using (GraphicsPath outerPath = new GraphicsPath())
            {
                outerPath.AddLines(this.m_activeBounds);

                using (LinearGradientBrush gradientBrush = this.GetGradientBackBrush())
                {
                    g.FillPath(gradientBrush, outerPath);
                }

                using (LinearGradientBrush shadowBrush = new LinearGradientBrush(shadowRectangle, this.TabBackColor, Color.Black, LinearGradientMode.Vertical))
                {
                    shadowBrush.Blend = shadowBlend;
                    g.FillRectangle(shadowBrush, shadowRectangle);
                }

                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.DrawPath(new Pen(this.ParentInternal.ActiveTabBorderColor), outerPath);
            }

            //Draw the inner border
            using (GraphicsPath innerPath = new GraphicsPath())
            {
                innerPath.AddLines(this.m_activeInnerBounds);

                Color lineColor = Color.FromArgb(120, 255, 255, 255);
                g.DrawPath(new Pen(lineColor), innerPath);
            }

            if (this.CanClose)
            {
                this.DrawCloseButton(g);
            }
        }

        private void DrawInactiveTabBackground(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.None;

            using (GraphicsPath outerPath = new GraphicsPath())
            {
                outerPath.AddLines(this.m_inactiveBounds);

                using (LinearGradientBrush gradientBrush = this.GetGradientBackBrush())
                {
                    g.FillPath(gradientBrush, outerPath);
                }

                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.DrawPath(new Pen(this.ParentInternal.InactiveTabBorderColor), outerPath);
            }

            //Draw the inner border
            using (GraphicsPath innerPath = new GraphicsPath())
            {
                innerPath.AddLines(this.m_inactiveInnerBounds);

                Color lineColor = Color.FromArgb(120, 255, 255, 255);
                g.DrawPath(new Pen(lineColor), innerPath);
            }
        }

        protected LinearGradientBrush GetGradientBackBrush()
        {
            LinearGradientBrush b = new LinearGradientBrush(this.DisplayRectangle, Color.White, this.TabBackColor, LinearGradientMode.Vertical);
            Blend bl = new Blend();

            if (this.IsActive)
            {
                bl.Factors = new float[] {
				0.3f,
				0.4f,
				0.5f,
				1f,
				1f
			};
                bl.Positions = new float[] {
				0f,
				0.2f,
				0.35f,
				0.35f,
				1f
			};
            }
            else
            {
                bl.Factors = new float[] {
				0.3f,
				0.4f,
				0.5f,
				1f,
				0.8f,
				0.7f
			};
                bl.Positions = new float[] {
				0f,
				0.2f,
				0.4f,
				0.4f,
				0.8f,
				1f
			};
            }

            b.Blend = bl;

            return b;
        }
        #endregion

        #region "Paint"
        internal virtual void DrawControl(Graphics g)
        {
            if (this.IsActive)
            {
                DrawActiveTab(g);
            }
            else
            {
                DrawInactiveTab(g);
            }
        }

        private void DrawActiveTab(Graphics g)
        {
            //The proposedSize variable determines the size available to draw the text of the tab.
            Size proposedSize = new Size(this.Width - 5, this.Height);

            if (this.CanClose)
            {
                //If the tab can close then subtract the button's width
                proposedSize.Width -= 22;
                this.DrawCloseButton(g);
            }

            if (this.ParentInternal.DisplayFormIcon)
            {
                //If the tab will display an icon the subtract the icon's width
                proposedSize.Width -= 22;
                this.DrawFormIcon(g);
            }

            this.DrawTabText(g, proposedSize);
        }

        private void DrawFormIcon(Graphics g)
        {
            Rectangle iconRectangle = default(Rectangle);

            if (this.ParentInternal.RightToLeft == RightToLeft.Yes)
            {
                iconRectangle = new Rectangle(this.Right - 20, this.Top + 5, 17, 17);
            }
            else
            {
                iconRectangle = new Rectangle(this.Left + 5, this.Top + 5, 17, 17);
            }

            if (!this.IsActive)
            {
                iconRectangle.Offset(0, 2);
            }

            using (Bitmap bmp = new Bitmap(this.Form.Icon.Width, this.Form.Icon.Height, PixelFormat.Format32bppArgb))
            {
                using (Graphics bg = Graphics.FromImage(bmp))
                {
                    bg.DrawIcon(this.Form.Icon, 0, 0);
                }

                g.DrawImage(bmp, iconRectangle);
            }
        }

        private void DrawTabText(Graphics g, Size proposedSize)
        {
            Size s = default(Size);
            Rectangle textRectangle = default(Rectangle);
            TextFormatFlags textFlags = TextFormatFlags.WordEllipsis | TextFormatFlags.EndEllipsis;
            bool isRightToLeft = this.ParentInternal.RightToLeft == RightToLeft.Yes;

            if (isRightToLeft)
            {
                textFlags = textFlags | TextFormatFlags.Right;
            }

            s = TextRenderer.MeasureText(g, this.Form.Text, this.TabFont, proposedSize, textFlags);
            textRectangle = new Rectangle(this.Left + 5, this.Top + 8, proposedSize.Width, s.Height);

            if (isRightToLeft)
            {
                if (this.IsActive && this.CanClose)
                {
                    textRectangle.Offset(22, 0);
                }
            }
            else
            {
                if (this.ParentInternal.DisplayFormIcon)
                {
                    textRectangle.Offset(17, 0);
                }
            }

            if (!this.IsActive)
            {
                textRectangle.Offset(0, 2);
            }

            TextRenderer.DrawText(g, this.Form.Text, this.TabFont, textRectangle, this.TabForeColor, textFlags);
        }

        private void DrawCloseButton(Graphics g)
        {
            if (this.IsMouseOverCloseButton)
            {
                this.DrawActiveCloseButton(g);
            }
            else
            {
                this.DrawInactiveCloseButton(g);
            }
        }

        private void DrawActiveCloseButton(Graphics g)
        {
            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.AddLines(this.m_closeButtonBounds);

                using (SolidBrush backBrush = new SolidBrush(this.ParentInternal.CloseButtonBackColor))
                {
                    g.FillPath(backBrush, gp);
                }

                using (Pen borderPen = new Pen(this.ParentInternal.CloseButtonBorderColor))
                {
                    g.DrawPath(borderPen, gp);
                }
            }

            this.DrawCloseButtonGlyph(g, this.ParentInternal.CloseButtonHotForeColor);
        }

        private void DrawInactiveCloseButton(Graphics g)
        {
            this.DrawCloseButtonGlyph(g, this.ParentInternal.CloseButtonForeColor);
        }

        private void DrawCloseButtonGlyph(Graphics g, Color glyphColor)
        {
            g.SmoothingMode = SmoothingMode.None;

            using (GraphicsPath shadow = new GraphicsPath())
            {
                Matrix translateMatrix = new Matrix();
                Color shadowColor = Color.FromArgb(30, 0, 0, 0);

                shadow.AddLines(this.m_closeButtonGlyphBounds);
                translateMatrix.Translate(1, 1);
                shadow.Transform(translateMatrix);

                using (SolidBrush shadowBrush = new SolidBrush(shadowColor))
                {
                    g.FillPath(shadowBrush, shadow);
                }
                using (Pen shadowPen = new Pen(shadowColor))
                {
                    g.DrawPath(shadowPen, shadow);
                }
            }

            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.AddLines(this.m_closeButtonGlyphBounds);

                using (SolidBrush glyphBrush = new SolidBrush(glyphColor))
                {
                    g.FillPath(glyphBrush, gp);
                }
                using (Pen glyphPen = new Pen(glyphColor))
                {
                    g.DrawPath(glyphPen, gp);
                }
            }

            g.SmoothingMode = SmoothingMode.AntiAlias;
        }

        private void DrawInactiveTab(Graphics g)
        {
            //The proposedSize variable determines the size available to draw the text of the tab.
            Size proposedSize = new Size(this.Width - 5, this.Height);

            if (this.ParentInternal.DisplayFormIcon)
            {
                //If the tab will display an icon the subtract the icon's width
                proposedSize.Width -= 22;
                this.DrawFormIcon(g);
            }

            this.DrawTabText(g, proposedSize);
        }
        #endregion

        #region "Fade Animation"
        internal void StartAnimation(AnimationType animation)
        {
            //When the cursor is moved over the control very quick it causes some odd behavior with the animation
            //These two checks are done to make sure that the tab isn't needlessly added to the animation arraylist.
            if (animation == AnimationType.FadeIn && this.CurrentFrame == this.ParentInternal.Duration - 1)
            {
                return;
            }

            if (animation == AnimationType.FadeOut && this.CurrentFrame == 0)
            {
                return;
            }

            this.m_animationType = animation;
            if (((this.ParentInternal != null)))
            {
                this.IsAnimating = true;
            }
        }

        internal void OnAnimationTick(int newFrame)
        {
            this.m_currentFrame = newFrame;
            this.ParentInternal.Invalidate(this.DisplayRectangle, false);
        }

        internal void StopAnimation()
        {
            this.IsAnimating = false;
            this.ParentInternal.Invalidate(this.DisplayRectangle, false);
        }
        [DllImport("User32.dll", EntryPoint = "LoadCursorFromFileW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
        #endregion

        #region "CustomCursor"
        private static extern IntPtr LoadCursorFromFile(string filename);

        private Cursor GetCustomCursor(string fileName)
        {
            IntPtr hCursor = default(IntPtr);
            Cursor result = null;

            try
            {
                hCursor = LoadCursorFromFile(fileName);
                if (!IntPtr.Zero.Equals(hCursor))
                {
                    result = new Cursor(hCursor);
                }
            }
            catch (Exception)
            {
                //Catch but don't process the exception. If this method returns nothing then
                //the default Windows drag cursor will be used.
                return null;
            }
            return result;
        }
        #endregion

        #endregion

        #region "Events"

        #region "Layout"
        protected override void OnLayout(System.Windows.Forms.LayoutEventArgs levent)
        {
            this.m_activeBounds = new Point[] {
			new Point(-2, this.ParentInternal.Bottom),
			new Point(-2, this.Bottom),
			new Point(this.Left - 3, this.Bottom),
			new Point(this.Left, this.Bottom - 1),
			new Point(this.Left, this.Top + 3),
			new Point(this.Left + 2, this.Top),
			new Point(this.Right - 2, this.Top),
			new Point(this.Right, this.Top + 3),
			new Point(this.Right, this.Bottom - 1),
			new Point(this.Right + 2, this.Bottom),
			new Point(this.ParentInternal.Width, this.Bottom),
			new Point(this.ParentInternal.Width, this.ParentInternal.Bottom)
		};
            this.m_activeInnerBounds = new Point[] {
			new Point(-1, this.ParentInternal.Bottom),
			new Point(-1, this.Bottom + 1),
			new Point(this.Left - 4, this.Bottom + 1),
			new Point(this.Left + 1, this.Bottom),
			new Point(this.Left + 1, this.Top + 4),
			new Point(this.Left + 3, this.Top + 1),
			new Point(this.Right - 3, this.Top + 1),
			new Point(this.Right - 1, this.Top + 4),
			new Point(this.Right - 1, this.Bottom),
			new Point(this.Right + 3, this.Bottom + 1),
			new Point(this.ParentInternal.Width - 1, this.Bottom + 1),
			new Point(this.ParentInternal.Width - 1, this.ParentInternal.Bottom)
		};
            this.m_inactiveBounds = new Point[] {
			new Point(this.Left, this.Bottom),
			new Point(this.Left, this.Top + 5),
			new Point(this.Left + 2, this.Top + 2),
			new Point(this.Right - 2, this.Top + 2),
			new Point(this.Right, this.Top + 5),
			new Point(this.Right, this.Bottom)
		};
            this.m_inactiveInnerBounds = new Point[] {
			new Point(this.Left + 1, this.Bottom),
			new Point(this.Left + 1, this.Top + 6),
			new Point(this.Left + 3, this.Top + 3),
			new Point(this.Right - 3, this.Top + 3),
			new Point(this.Right - 1, this.Top + 6),
			new Point(this.Right - 1, this.Bottom)
		};

            if (this.ParentInternal.RightToLeft == RightToLeft.Yes)
            {
                this.m_closeButtonBounds = new Point[] {
				new Point(this.Left + 18, this.Top + 7),
				new Point(this.Left + 6, this.Top + 7),
				new Point(this.Left + 4, this.Top + 9),
				new Point(this.Left + 4, this.Top + 20),
				new Point(this.Left + 6, this.Top + 22),
				new Point(this.Left + 18, this.Top + 22),
				new Point(this.Left + 20, this.Top + 20),
				new Point(this.Left + 20, this.Top + 9),
				new Point(this.Left + 18, this.Top + 7)
			};
                Point startPoint = new Point(this.Left + 8, this.Top + 11);
                this.m_closeButtonGlyphBounds = new Point[] {
				new Point(startPoint.X, startPoint.Y),
				new Point(startPoint.X + 2, startPoint.Y),
				new Point(startPoint.X + 4, startPoint.Y + 2),
				new Point(startPoint.X + 6, startPoint.Y),
				new Point(startPoint.X + 8, startPoint.Y),
				new Point(startPoint.X + 5, startPoint.Y + 3),
				new Point(startPoint.X + 5, startPoint.Y + 4),
				new Point(startPoint.X + 8, startPoint.Y + 7),
				new Point(startPoint.X + 6, startPoint.Y + 7),
				new Point(startPoint.X + 4, startPoint.Y + 5),
				new Point(startPoint.X + 2, startPoint.Y + 7),
				new Point(startPoint.X, startPoint.Y + 7),
				new Point(startPoint.X + 3, startPoint.Y + 4),
				new Point(startPoint.X + 3, startPoint.Y + 3),
				new Point(startPoint.X, startPoint.Y)
			};
            }
            else
            {
                this.m_closeButtonBounds = new Point[] {
				new Point(this.Right - 18, this.Top + 7),
				new Point(this.Right - 6, this.Top + 7),
				new Point(this.Right - 4, this.Top + 9),
				new Point(this.Right - 4, this.Top + 20),
				new Point(this.Right - 6, this.Top + 22),
				new Point(this.Right - 18, this.Top + 22),
				new Point(this.Right - 20, this.Top + 20),
				new Point(this.Right - 20, this.Top + 9),
				new Point(this.Right - 18, this.Top + 7)
			};
                Point startPoint = new Point(this.Right - 16, this.Top + 11);
                this.m_closeButtonGlyphBounds = new Point[] {
				new Point(startPoint.X, startPoint.Y),
				new Point(startPoint.X + 2, startPoint.Y),
				new Point(startPoint.X + 4, startPoint.Y + 2),
				new Point(startPoint.X + 6, startPoint.Y),
				new Point(startPoint.X + 8, startPoint.Y),
				new Point(startPoint.X + 5, startPoint.Y + 3),
				new Point(startPoint.X + 5, startPoint.Y + 4),
				new Point(startPoint.X + 8, startPoint.Y + 7),
				new Point(startPoint.X + 6, startPoint.Y + 7),
				new Point(startPoint.X + 4, startPoint.Y + 5),
				new Point(startPoint.X + 2, startPoint.Y + 7),
				new Point(startPoint.X, startPoint.Y + 7),
				new Point(startPoint.X + 3, startPoint.Y + 4),
				new Point(startPoint.X + 3, startPoint.Y + 3),
				new Point(startPoint.X, startPoint.Y)
			};
            }
        }
        #endregion

        #region "DragDrop Events"
        protected override void OnGiveFeedback(System.Windows.Forms.GiveFeedbackEventArgs gfbevent)
        {
            gfbevent.UseDefaultCursors = this.m_dragCursor == null;

            if ((gfbevent.Effect & DragDropEffects.Move) == DragDropEffects.Move)
            {
                System.Windows.Forms.Cursor.Current = this.m_dragCursor;
            }
            else
            {
                System.Windows.Forms.Cursor.Current = Cursors.No;
            }
        }
        #endregion

        #region "Mouse Events"
        protected override void OnMouseEnter(System.EventArgs e)
        {
            this.IsMouseOver = true;

            if (this.CanAnimate && !this.IsActive)
            {
                this.StartAnimation(AnimationType.FadeIn);
            }

            if (this.Form != null)
            {
                this.ParentInternal.UpdateToolTip(this.Form.Text);
            }
        }

        protected override void OnMouseLeave(System.EventArgs e)
        {
            //Reset the mouse over fields to False
            this.IsMouseOver = false;
            this.IsMouseOverCloseButton = false;

            if (this.CanAnimate)
            {
                if (!this.IsActive)
                {
                    //If not the currently active tab
                    if (this.IsAnimating)
                    {
                        //If the tab is currently animating then change it's animation type to properly fade
                        //back to the inactive color.
                        this.m_animationType = AnimationType.FadeOut;
                    }
                    else
                    {
                        //The cursor was still over the tab and animation had finished so we need to fade
                        //from the mouseover color to the inactive color
                        this.StartAnimation(AnimationType.FadeOut);
                    }
                }
                else
                {
                    //If it is the active tab then reset the current frame to 0 because the tab
                    //might have been selected while animation was in process
                    this.m_currentFrame = 0;
                }
            }
            else
            {
                //If the tab cannot animate then invalidate the tab to repaint with the inactive color
                this.ParentInternal.Invalidate(this.DisplayRectangle, false);
            }
        }

        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            Size dragsize = SystemInformation.DragSize;
            this.m_owner.OnMdiTabClicked(new MdiTabStripTabClickedEventArgs(this));

            if (this.CanDrag)
            {
                //If the tab can be dragged, which is determined by the TabPermenance property, then set the
                //drag box and load the custom cursor.
                this.m_dragBox = new Rectangle(new Point(e.X - (dragsize.Width / 2), e.Y - (dragsize.Height / 2)), dragsize);

                if (this.m_dragCursor == null)
                {
                    string filePath = System.IO.Path.Combine(Application.StartupPath, "MyDragTab.cur");
                    this.m_dragCursor = this.GetCustomCursor(filePath);
                }
            }

            if (!this.IsActive)
            {
                //Set the isSwitching field. This prevents the tab from being closed in the MouseUp event
                //if the cursor is over the area in which the close button will be displayed.
                this.m_isSwitching = true;
                this.Form.Activate();
            }
        }

        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            this.m_dragBox = Rectangle.Empty;

            //If the tab is closable and the user is not switching tabs and the mouse was clicked over the
            //close button then close the form. The tab is removed via the FormClose event handler in MdiTabStrip class.
            if (this.CanClose && !this.m_isSwitching && this.closeButtonHitTest(e.X, e.Y))
            {
                this.Form.Close();
            }

            this.m_isSwitching = false;
        }

        protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                if (this.CanDrag)
                {
                    //If the tab can be dragged, which is determined by the TabPermenace property, then.
                    if (this.m_dragBox != Rectangle.Empty && !this.m_dragBox.Contains(e.X, e.Y))
                    {
                        //If the cursor has been moved out of the bounds of the drag box while the left
                        //mouse button is down then initiate dragging by calling the DoDragDrop method.

                        this.m_isSwitching = false;
                        DragDropEffects dropEffects = this.DoDragDrop(this, DragDropEffects.Move);
                        this.m_dragBox = Rectangle.Empty;
                    }
                }
            }
            else
            {
                //if active then test if mouse cursor is over the close button to display the tool tip.
                if (this.IsActive)
                {
                    this.IsMouseOverCloseButton = this.closeButtonHitTest(e.X, e.Y);
                }
            }
        }
        #endregion

        #endregion

    }


    //=======================================================
    //Service provided by Telerik (www.telerik.com)
    //Conversion powered by NRefactory.
    //Twitter: @telerik
    //Facebook: facebook.com/telerik
    //=======================================================
}